package com.jerry.seckill.web;

import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.jerry.seckill.dto.ExecutionResult;
import com.jerry.seckill.dto.Exposer;
import com.jerry.seckill.dto.SeckillResult;
import com.jerry.seckill.entity.Seckill;
import com.jerry.seckill.enums.SeckillStateEnum;
import com.jerry.seckill.exception.RepeatSeckillException;
import com.jerry.seckill.exception.SeckillCloseException;
import com.jerry.seckill.service.SeckillService;

/** 
 * @describe 控制器
 */ 
@Controller 
@RequestMapping(value = "/seckill")   // url:/模块/资源/{id}/细分 
public class SeckillController {
	private final Logger logger = LoggerFactory.getLogger(this.getClass()); 

	public SeckillController(){ 
		System.out.println("SeckillController被初始化"); 
	} 
	
	@Autowired 
	private SeckillService seckillService; 
	
	// 获取列表页方式一
//	@RequestMapping(name="/list",method=RequestMethod.GET)
//	public String list2(Model model){ 
//		// 获取列表页 
//		List<Seckill> list = seckillService.getSeckillList(); 
//		model.addAttribute(list); 
//		// list.jsp(模板) + model(数据) = ModelAndView 
//		return "list";     //相当于 /WEB-INF/jsp/list.jsp 
//	} 
	
	// 获取列表页方式二
	// 该注解为组合注解，等价于 @RequestMapping(name="/list",method=RequestMethod.GET) 
	@GetMapping(value = "/list") 
	public ModelAndView list(Model model){ 
		// 获取列表页 
		List<Seckill> list = seckillService.getSeckillList(); 
		model.addAttribute(list); 
		return new ModelAndView("list").addObject("list",list); // /WEB-INF/jsp/list.jsp 
	} 
	
	@GetMapping("/{seckillId}/detail") 
	public String detail(@PathVariable("seckillId") Long seckillId, Model model){ 
		if(null == seckillId){ 
			// 重定向 
			return "redirect:/seckill/list"; 
		} 
		Seckill seckill = seckillService.getById(seckillId); 
		if(null == seckill){
			// 请求转发 
			return "forward:/seckill/list"; 
		} 
		model.addAttribute("seckill",seckill); 
		return "detail"; 
	} 
	
	//以ajax json方式获取暴露url 
	@PostMapping(value = "/{seckillId}/exposer",
			     produces = {"application/json;charset=UTF-8"}) 
	@ResponseBody 
	public SeckillResult<Exposer> exposer(@PathVariable("seckillId")Long seckillId){ 
		SeckillResult<Exposer> result; 
		try { 
			Exposer exposer = seckillService.exportSeckillUrl(seckillId); 
			result = new SeckillResult<Exposer>(true,exposer);   //正确时 返回暴露实体对象
		} catch (Exception e) { 
			logger.error(e.getMessage(), e); 
			result = new SeckillResult<Exposer>(false, e.getMessage());  //异常时 返回异常信息
		} 
		
		return result; 
	} 
	
	//以ajax json方式返回秒杀结果
	@PostMapping(value = "/{seckillId}/{md5}/execution",
			     produces = {"application/json;charset=UTF-8"}) 
	@ResponseBody 
	public SeckillResult<ExecutionResult> execute(
			@PathVariable("seckillId")Long seckillId, 
			@PathVariable("md5")String md5, 
			@CookieValue(value = "killPhone",required = false) String phone){ 
		
		if(StringUtils.isEmpty(phone)){ 
			return new SeckillResult<ExecutionResult>(false,"未注册"); 
		} 
		try{ 
			ExecutionResult execution = seckillService.executeSeckill(seckillId,phone,md5); 
			//使用存储过程
//			ExecutionResult execution = seckillService.executeSeckillProcedure(seckillId, phone, md5);
			return new SeckillResult<ExecutionResult>(true,execution); 
		} catch (SeckillCloseException e1){ 
			ExecutionResult execution = new ExecutionResult(seckillId, SeckillStateEnum.END); 
			return new SeckillResult<ExecutionResult>(true,execution); 
		} catch (RepeatSeckillException e2){ 
			ExecutionResult execution = new ExecutionResult(seckillId, SeckillStateEnum.REPEAT_KILL); 
			return new SeckillResult<ExecutionResult>(true,execution); 
		} catch (Exception e){ 
			logger.error(e.getMessage(),e); 
			ExecutionResult execution = new ExecutionResult(seckillId, SeckillStateEnum.INNER_ERROR); 
			return new SeckillResult<ExecutionResult>(true,execution); 
		} 
	} 
	
	@GetMapping("/time/now") 
	@ResponseBody 
	public SeckillResult<Long> time(){ 
		Date now = new Date(); 
		return new SeckillResult<Long>(true,now.getTime()); 
	} 
}